package com.jsftoolkit.base;

import java.io.IOException;

import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.context.FacesContext;
import javax.faces.render.Renderer;

import com.jsftoolkit.ajax.AjaxContext;
import com.jsftoolkit.base.components.UIDataProcessor;
import com.jsftoolkit.utils.IOExceptionWrapper;
import com.jsftoolkit.utils.Utils;

/**
 * {@link UIData}/{@link JsfIterator} renderer without all the extra markup of
 * a data table. This renderer defers all rendering to its children, so it can
 * be used in any render kit.
 * 
 * @author noah
 * 
 */
public class GenericDataRenderer extends Renderer {

	@Override
	public void decode(FacesContext context, UIComponent component) {
		super.decode(context, component);

		AjaxContext ajax = AjaxContext.getCurrentInstance();
		if (ajax.isAjaxRequest(context)) {
			ajax.decode(context, component);
		}
	}

	@Override
	public void encodeChildren(FacesContext context, UIComponent component)
			throws IOException {
		Utils.notNull(context, "context");
		Utils.notNull(component, "component");

		JsfIterator data;
		if (component instanceof UIData) {
			data = new UIDataProcessor.UIDataWrapper((UIData) component);
		} else {
			data = (JsfIterator) component;
		}

		try {
			UIDataProcessor.iterate(context, data, new UIDataProcessor() {
				public void processChild(FacesContext context, UIComponent child) {
					try {
						child.encodeAll(context);
					} catch (IOException e) {
						// wrap it in a runtime exception so it will
						// bubble out
						throw new IOExceptionWrapper(e);
					}
				}
			});
		} catch (IOExceptionWrapper e) {
			throw e.getWrapped();
		}
	}

	@Override
	public boolean getRendersChildren() {
		return true;
	}
}
